package com.tvunetworks.center.device.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tvunetworks.center.common.constant.LocalConstant;
import com.tvunetworks.center.common.constant.ReceiverCommandConstant;
import com.tvunetworks.center.common.exception.ServerException;
import com.tvunetworks.center.common.feign.UserFeignInterface;
import com.tvunetworks.center.common.model.*;
import com.tvunetworks.center.common.model.param.receiver.GetAllPeerListByFiltersParam;
import com.tvunetworks.center.common.model.param.search.SlugInfo;
import com.tvunetworks.center.common.model.ps.PSR;
import com.tvunetworks.center.common.model.ps.PST;
import com.tvunetworks.center.common.util.*;
import com.tvunetworks.center.device.constant.DeviceConstant;
import com.tvunetworks.center.device.mapper.DeviceResoureRelationMapper;
import com.tvunetworks.center.device.mapper.ExtendExternalMapper;
import com.tvunetworks.center.device.mapper.ExternalReceiverRelationMapper;
import com.tvunetworks.center.device.mapper.MyDeviceMapper;
import com.tvunetworks.center.device.model.DeviceSy;
import com.tvunetworks.center.device.model.MyDevice;
import com.tvunetworks.center.device.model.PtsPrs;
import com.tvunetworks.center.device.model.json.DeviceIpPort;
import com.tvunetworks.center.device.model.param.AddExtToReceiverParam;
import com.tvunetworks.center.device.model.param.DevicePlatformParam;
import com.tvunetworks.center.device.model.result.ResultConstant;
import com.tvunetworks.center.device.model.vo.NotConnectR;
import com.tvunetworks.center.device.model.vo.PackTokenResult;
import com.tvunetworks.center.device.model.vo.SlotVo;
import com.tvunetworks.center.device.service.*;
import com.tvunetworks.center.device.service.feign.RwsFeignService;
import com.tvunetworks.center.device.service.feign.TokenFeignService;
import com.tvunetworks.center.device.service.feign.UserFeignService;
import com.tvunetworks.center.device.util.MemcacheUtil;
import com.tvunetworks.center.device.util.RedisUtil;
import com.tvunetworks.center.device.util.ThreadPoolUtil;
import com.tvunetworks.center.gs.model.Device;
import com.tvunetworks.center.gs.model.DeviceGeo;
import com.tvunetworks.crawler.model.T;
import lombok.extern.slf4j.Slf4j;
import net.spy.memcached.MemcachedClient;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;


/**
 * @program: tvucc-instance
 * @description: UserServiceImpl
 * @author lebronchen
 * @create: 2019-02-28 16:53
 **/
@Service
@Slf4j
public class DeviceServiceImpl implements DeviceService {

    @Value("${tvucc.url}")
    private String tvuccUrl;
    @Value("${tpc.url}")
    private String tpcUrl;
    @Value("${detailInfo}")
    private String detailInfo;

    @Value("${userserviceAuth}")
    private String userserviceUrl;

    @Value("${gridPack}")
    private String gridPack;
    @Value("${gridSdi}")
    private String gridSdi;
    @Value("${geo.service.url}")
    private String geoServiceUrl;
    @Value("${isProduct}")
    private boolean isProduct;
    @Value("${newUserservice.interface.url}")
    private String userservice;
    @Autowired
    private ExtService extService;

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    @Qualifier("tpdsMemcacheClient")
    private MemcachedClient tpdsMemcacheClient;
    @Autowired
    @Qualifier("psMemcacheClient")
    private MemcachedClient psMemcacheClient;
    @Autowired
    private MyDeviceMapper myDeviceMapper;
    @Autowired
    private MyDeviceService myDeviceService;
    @Autowired
    private DeviceResoureRelationService deviceResoureRelationService;
    @Autowired
    private DeviceResoureRelationMapper deviceResoureRelationMapper;
    @Autowired
    private ExternalReceiverRelationService externalReceiverRelationService;
    @Autowired
    private ExternalReceiverRelationMapper externalReceiverRelationMapper;
    @Autowired
    private UserFeignService userFeignService;
    @Autowired
    private TokenFeignService tokenFeignService;
    @Autowired
    private RwsFeignService rwsFeignService;
    @Autowired
    private DeviceService deviceService;
    //    @Autowired
    @Resource(name = "redisDevTemplate")
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private MemcacheUtil memcacheUtil;

    @Autowired
    private UserFeignInterface userFeignInterface;
    @Autowired
    private ExtendExternalMapper extendExternalMapper;
    @Autowired
    private RedisUtil redisUtil;

    @Value("${listNotConnectR.stepNum:1000}")
    private int listNotConnectRStepNum;
    @Value("${receiver.s3.upload.region:us-east-1}")
    private String s3UploadRegion;
    @Value("${receiver.s3.upload.bucket:pp-va-001}")
    private String s3UploadBucket;
    @Value("${receiver.s3.upload.directoryName:recordings}")
    private String s3UploadDirectoryName;
    @Value("${receiver.s3.upload.accessKey:demo}")
    private String s3UploadAccessKey;
    @Value("${receiver.s3.upload.accessSecret:demo}")
    private String s3UploadAccessSecret;
    @Value("${receiver.s3.upload.categoryId:2152857600}")
    private String receiverS3UploadCategoryId;
    @Value("${receiver.s3.upload.operationType:404}")
    private String receiverS3UploadOperationType;
    @Value("${initReceiverUploadParam.retry.times:3}")
    private int initReceiverUploadParamRetryTimes;
    @Value("${invalidDeviceSaveRedisTime:60}")
    private Long  invalidDeviceSaveRedisTime;
    @Value("${invalidDeviceRedisKeyName:no-exciting}")
    private String  invalidDeviceRedisKeyName;
    @Override
    public Device getMemDevice(String peerId) {
        if (StringUtils.isEmpty(peerId)) {
            return null;
        }
        if (peerId.length() > 32) {
            log.error("DeviceServiceImpl getMemDevice peerId size error peerId:{}", peerId);
            return null;
        }
        return (Device) tpdsMemcacheClient.get(DeviceConstant.MemcacheKey.STATUS_FOR_GRIDWITCH + peerId);
    }

    @Override
    public List<String> getReceiverByPeerId(List<String> rid) {
        if (CollectionUtils.isEmpty(rid)) {
            return new ArrayList<>();
        } else {
            return myDeviceMapper.getReceiverIdPeerId(rid);
        }
    }



    @Override
    public MyDevice getDBDevice(String peerId) {
        return myDeviceMapper.getMyDeviceByPeerId(peerId);
    }

    @Override
    public Device getDevice4DB(String peerId) {
        return myDeviceMapper.getDeviceByPeerId(peerId.toLowerCase());
    }

    @Override
    public void updateDevice(MyDevice device) {
        myDeviceMapper.updateByPrimaryKeySelective(device);
    }

    @Override
    public List<Device> listMemDevice(Collection<String> peerIds) {
        if (peerIds == null || peerIds.size() == 0) {
            return null;
        }
        HashSet<String> peerIdSet = new HashSet<>(peerIds);
        List<Device> list = new ArrayList<>();
        for (String peerId : peerIdSet) {
            Device device = this.getMemDevice(peerId);
            if (device != null) {
                list.add(device);
            }
        }
        return list;
    }

    @Override
    public Device getCurrentDevice(String peerId) {
        if (StringUtils.isBlank(peerId)) {
            return null;
        }
        Device memDevice = this.getMemDevice(peerId.toLowerCase());
        if (memDevice != null) {
            if (LocalConstant.DeviceStatus.ONLINE.equals(memDevice.getStatus()) || LocalConstant.DeviceStatus.OFFLINE.equals(memDevice.getStatus())) {
                memDevice.setLivePeerId(null);
                memDevice.setLivePeerName(null);
            }
            if (StringUtils.isNotBlank(memDevice.getPlatform())) {
                memDevice.setPlatform(memDevice.getPlatform().trim());
            }
            return memDevice;
        }
        if ( redisUtil.get(invalidDeviceRedisKeyName+"_"+peerId.toLowerCase())!=null){
            return  null;
        }

        Device dbDevice = myDeviceMapper.getDeviceByPeerId(peerId.toLowerCase());
        if (dbDevice == null) {
            redisUtil.set(invalidDeviceRedisKeyName+"_"+peerId.toLowerCase() ,System.currentTimeMillis(),invalidDeviceSaveRedisTime);
            return null;
        }
        dbDevice.setStatus(LocalConstant.DeviceStatus.OFFLINE);
        dbDevice.setLivePeerId(null);
        dbDevice.setLivePeerName(null);
        if (StringUtils.isNotBlank(dbDevice.getPlatform())) {
            dbDevice.setPlatform(dbDevice.getPlatform().trim());
        }

        if (LocalConstant.DeviceStatus.LIVING.equals(dbDevice.getStatus())
                && StringUtils.isNotBlank(dbDevice.getLivePeerId())
                && StringUtils.isBlank(dbDevice.getLivePeerName())) {
            Device d = this.getCurrentDevice(dbDevice.getLivePeerId());
            if (d != null) {
                dbDevice.setLivePeerName(d.getName());
            }
        }

        return dbDevice;
    }

    @Override
    public List<Device> listCurrentDevice(Collection<String> peerIds) {
        if (CollectionUtils.isEmpty(peerIds)) {
            return null;
        }

        // 通过 Set 去重
        HashSet<String> peerIdSet = new HashSet<>();
        for (String peerId : peerIds) {
            peerIdSet.add(peerId.toLowerCase());
        }

        Set<String> illegalPids = peerIdSet.stream().filter(e -> e.length() > 32).collect(Collectors.toSet());
        if (!CollectionUtils.isEmpty(illegalPids)) {
            log.error("DeviceServiceImpl listCurrentDevice peerId size error illegalPids:{}", illegalPids);
            peerIdSet.removeAll(illegalPids);
        }

        if (CollectionUtils.isEmpty(peerIdSet)) {
            return null;
        }

        // 封装查询 memcache 的 key
        HashSet<String> memcacheKeys = new HashSet<>();
        for (String peerId : peerIdSet) {
            memcacheKeys.add(DeviceConstant.MemcacheKey.STATUS_FOR_GRIDWITCH + peerId.toLowerCase().trim());
        }

        // 记录 memcache 中查询到的 peerId
        Set<String> inMemPeerIds = new HashSet<>();
        // 记录结果
        List<Device> resultList = new ArrayList<>();

        Map<String, Object> bulkMap = memcacheUtil.multiGet(tpdsMemcacheClient, memcacheKeys);
//        Map<String, Object> bulkMap = tpdsMemcacheClient.getBulk(memcacheKeys);
        if (!CollectionUtils.isEmpty(bulkMap)) {
            Collection<Object> values = bulkMap.values();
            for (Object o : values) {
                Device d = (Device) o;
                resultList.add(d);
                inMemPeerIds.add(d.getPeerId());
            }
        }

        // 移除掉 memcache 中查询到的 peerId，得到需要查询 DB 的 peerIds
        peerIdSet.removeAll(inMemPeerIds);

        if (!CollectionUtils.isEmpty(peerIdSet)) {
            List<Device> dbList = myDeviceMapper.listDevices(peerIdSet);
            if (!CollectionUtils.isEmpty(dbList)) {
                for (Device dbDevice : dbList) {
                    dbDevice.setStatus(LocalConstant.DeviceStatus.OFFLINE);
                    dbDevice.setLivePeerId(null);
                    dbDevice.setLivePeerName(null);
                    if (StringUtils.isNotBlank(dbDevice.getPlatform())) {
                        dbDevice.setPlatform(dbDevice.getPlatform().trim());
                    }
                }
                resultList.addAll(dbList);
            }
        }

        for (Device device : resultList) {
            if (LocalConstant.DeviceStatus.LIVING.equals(device.getStatus())
            && StringUtils.isNotBlank(device.getLivePeerId())
            && StringUtils.isBlank(device.getLivePeerName())) {
                Device d = this.getCurrentDevice(device.getLivePeerId());
                if (d != null) {
                    device.setLivePeerName(d.getName());
                }
            }
        }

        return resultList;
    }

    @Override
    public Map<String, String> listDeviceMetadata(Collection<String> peerIds) {
        Map<String, String> result = new HashMap<>();
        List<Device> listDBDevices = myDeviceMapper.listDevices(peerIds);
        if(listDBDevices != null && listDBDevices.size() > 0){
            for (Device listDBDevice : listDBDevices) {
                result.put(listDBDevice.getPeerId(),listDBDevice.getMetaData());
            }
        }
        return result;
    }

    @Override
    public Result<String> updateDeviceName(String peerId, String name, String type, String session) {


        log.error("==updateDeviceName name===:" + name);
        session = getSession();
//        String uncode = getUnicode(name);
//        System.out.println("====unicode===="+uncode);
//        log.error("updateDeviceName:"+name);
        String deviceType = "";
        if ("T".equals(type)) {
            deviceType = "0";
        } else {
            deviceType = "1";
        }

        String param = "{\"peerId\":\"" + peerId + "\",\"deviceType\":\"" + deviceType + "\",\"deviceName\":\"" + name + "\"}";
        if (!tpcUrl.contains("http")) {
            tpcUrl = "http://" + tpcUrl;
        }
//        tpcUrl ="http://10.12.22.222:8090/tpc";
        log.error("updateDeviceName param:" + name);
        String url = tpcUrl + "/editDeviceName.action?deviceInfo={param}&session=" + session;
//        String url = "http://10.12.22.172:8080/tpc/editDeviceName.action?deviceInfo={param}&session="+session;

        log.error(" tpc editDeviceName :url:{}", url);
        log.error(" URLEncoder.encode(param.toString()" + URLEncoder.encode(param.toString()));
        String body = null;
        HttpHeaders requestHeaders = new HttpHeaders();
        List cookieList = new ArrayList<>();
        Map cookieMap = new HashMap();
        cookieMap.put("SID", session);
        cookieList.add(cookieMap);
        requestHeaders.put("Cookie", cookieList);
        HttpEntity<String> requestEntity = new HttpEntity<String>(null, requestHeaders);
        log.error("URLEncoder.encode(param.toString()");
        try {

            ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class, URLEncoder.encode(param.toString(), "UTF-8"));
//            ResponseEntity<String> responseEntitdy = restTemplate.getForEntity(url, String.class,param);
//            log.info("tpc editDeviceName :result:{}", responseEntity);
            body = responseEntity.getBody();
        } catch (RestClientException e) {
            log.error("updateDeviceName Exception===:" + e.getMessage());
            log.error("msg:{},e:{}",e.getMessage(),e);
        } catch (UnsupportedEncodingException ex) {
            log.error("updateDeviceName UnsupportedEncodingException===:" + ex);
        }
        log.error("updateDeviceName Result body===:" + body);
        if (!StringUtils.contains(body, "Success")) {
            return ResultUtil.error("81100403", "editDeviceName name failed", body);
        }
//        else{
//            try {
//                String beName = name+"=="+body+"==="+URLEncoder.encode(param.toString(), "UTF-8");
//                myDeviceMapper.updateDeviceNameToRemark(peerId,beName);
//            } catch (UnsupportedEncodingException e) {
//                log.error("msg:{},e:{}",e.getMessage(),e);
//            }
//        }
        return ResultUtil.success(body);
    }

/*    *//**
     *
     * @param source source
     * @return String
     *//*
    public static String getUnicode(String source) {
        String returnUniCode = null;
        String uniCodeTemp = null;
        for (int i = 0; i < source.length(); i++) {
            uniCodeTemp = "\\u" + Integer.toHexString((int) source.charAt(i));//使用char类的charAt()的方法

            returnUniCode = returnUniCode == null ? uniCodeTemp : returnUniCode + uniCodeTemp;
        }
        System.out.print(source + " 's unicode = " + returnUniCode);
        return returnUniCode;//返回一个字符的unicode的编码值
    }*/

    @Override
    public Result<String> updateAnywhereName(String peerId, String name, String session) {

        PackTokenResult modifyResult = null;
        try {
            modifyResult = modifyPackName(name,peerId,session);
        } catch (Exception e) {
            log.error("updateAnywhereName is failed ",e);
            return  ResultUtil.error(e.getMessage());
        }
        return ResultUtil.success(modifyResult);
    }

    @Override
    public void setExtToMemcache(Device device) {
        String peerId = device.getPeerId();
        if (StringUtils.isBlank(peerId)) {
            return;
        }
        tpdsMemcacheClient.set(DeviceConstant.MemcacheKey.STATUS_FOR_GRIDWITCH + peerId, 0, device);
    }

    @Override
    public void deleteExtFromMemcache(String peerId) {
        tpdsMemcacheClient.delete(DeviceConstant.MemcacheKey.STATUS_FOR_GRIDWITCH + peerId);
    }

    @Override
    public String queryDetail(String peerId) throws IOException {
        List list = new ArrayList();
        if (StringUtils.isBlank(peerId)) {
            return "[]";
        }
        String[] pids = peerId.split(",");
        for (String pid : pids) {
            String result = stringRedisTemplate.opsForValue().get(detailInfo + peerId.toLowerCase());
            Map resultMap = new HashMap();
            ObjectMapper resultMapper = new ObjectMapper();
            resultMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
            if (StringUtils.isNotEmpty(result)) {
                T t = resultMapper.readValue(result, T.class);
                if (t != null) {
                    List<T.TIME> timeList = t.getTIME();
                    T.BATTERY battery = t.getBattery();
                    T.MEDIA media = t.getMedia();

                        resultMap.put("CurrentTPackBatteryRaw", JsonUtil.toJsonStr(battery).toUpperCase().replaceAll("NULL", "null"));
                        if (t.getCpu() != null) {
                            resultMap.put("cpu", JsonUtil.toJsonStr(t.getCpu()));
                        }
                        List array = new ArrayList();
                        int timeListSize = timeList.size();
                        if (timeListSize > 0) {
                            List<T.TIME.SLOT> slots = timeList.get(timeListSize - 1).getSLOT();
                            for (T.TIME.SLOT slot : slots) {
                                Map slotMap = new HashMap();
                                slotMap.put("Index", slot.getID());
                                slotMap.put("SignalType", slot.getTYPE());
                                slotMap.put("CarrierName", slot.getCops());
                                slotMap.put("IpStr", slot.getIP());
                                slotMap.put("SignalStrength", slot.getCsq());
                                slotMap.put("Speed", slot.getSPEED());
                                array.add(slotMap);
                            }
                        }
                        resultMap.put("Slots", array);
                        resultMap.put("media", media);
                        resultMap.put("peerId", pid);

                        // add platform
                        String platform = null;
                        Device device = this.getCurrentDevice(pid);
                        if (device != null) {
                            platform = device.getPlatform();
                        }
                        resultMap.put("platform", platform);
                        list.add(resultMap);

                }
            }
        }

        String rs = JsonUtil.toJsonStr(list);
        return rs;
    }

    /**
     *
     * @param peerId peerId
     * @return String
     * @throws IOException 编译异常
     */
    public String queryBatteryById(String peerId) throws IOException {
        String result = stringRedisTemplate.opsForValue().get(detailInfo + peerId.toLowerCase());
        String resultInfo = "";
        ObjectMapper resultMapper = new ObjectMapper();
        resultMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
        if (StringUtils.isNotEmpty(result)) {
            T t = resultMapper.readValue(result, T.class);

            if (t != null) {
                T.BATTERY battery = t.getBattery();
                resultInfo = JsonUtil.toJsonStr(battery).toLowerCase();
            }
        }
        return resultInfo;
    }

    @Override
    public String getSwitchType(String db, String matrixId) {
        String result = "3";
        if (matrixId != null && matrixId.length() >= 16 && db != null && !db.equals("")) {
            matrixId = matrixId.substring(0, 16);
            List<Map<String, String>> switchType = myDeviceMapper.getSwitchType(db, matrixId);
            if (switchType == null){

                return result;
            }
            for (Map<String, String> map : switchType) {
                if (map.get("attr_name").toLowerCase().equals("mode")) {
                    if (map.get("attr_value").toLowerCase().equals("normal")) {
                        result = "2";
                    } else {
                        result = "1";
                    }
                    break;
                }
            }
        }
        return result;
    }

    @Override
    public List<Device> listAllDevices(SearchDeviceParam param) {
        if (param.isNullType() || param.isNullTypeForMySource()) {
            return new ArrayList<>();
        }
        String typeCondition = this.packageTypeCondition(param);
        String condition = param.getCondition();
        condition = MyUtil.formatCondition(condition);
        List<String> listPeerIds = myDeviceMapper.listAllPeerIdFilterByTypeAndCondition(condition, typeCondition);
        if (CollectionUtils.isEmpty(listPeerIds)) {
            return new ArrayList<Device>(0);
        }
        List<Device> listDBDevices = myDeviceMapper.listDevices(listPeerIds);
       // List<Device> listDevice = this.listCurrentDevice(Arrays.asList(new ListDeviceParam(listPeerIds).getPeerIds().split(",")));
        List<Device> resultList = new ArrayList<>();
        // 过滤状态
        for (Device device : listDBDevices) {
            String status = "0";
            if (device != null) {
                Device memDevice = this.getMemDevice(device.getPeerId());
                if (memDevice != null) {
                    device.setStatus(memDevice.getStatus());
                    status = memDevice.getStatus();
                }
            }
            boolean statusExist;
            statusExist = param.isStatusExistByUser(status);
            if (statusExist && device != null) {
                resultList.add(device);
            }
        }
        return resultList;
    }

    @Override
    public PreloadParam getRPreloadMessage(String peerId) {
        List<PreloadXModel> preloadXModels = deviceResoureRelationMapper.listPreloadXModelByRid(peerId);
        List<PreloadExtModel> preloadExtModels = externalReceiverRelationMapper.listPreloadExtModelByRid(peerId);
        PreloadParam preloadParam = new PreloadParam(peerId, String.valueOf(System.currentTimeMillis()), preloadXModels, preloadExtModels);
        return preloadParam;
    }

    @Override
    public void preloadExtXToR(String rid) {
        PreloadParam preloadParam = this.getRPreloadMessage(rid);
     /*   if (preloadParam == null) {
            log.error("preloadExtXToR getRPreloadMessage return null rid:{}", rid);
            return;
        }*/
        log.error("preloadExtXToR rid:[{}] param:[{}]", rid, preloadParam);
        rwsFeignService.preload(preloadParam);
    }
    @Override
    public void preloadEventExtToR(String rid) {
        List<PreloadXModel> preloadXModels = deviceResoureRelationMapper.listPreloadXModelByRid(rid);
        List<PreloadExtModel> preloadExtModels = externalReceiverRelationMapper.listPreloadEventExtModelByRid(rid);
//        log.error("4.start send to R preloadExtModels="+ JSONUtils.toJSONString(preloadExtModels) +",and rid="+rid);
        PreloadParam preloadParam = new PreloadParam(rid, String.valueOf(System.currentTimeMillis()), preloadXModels, preloadExtModels);
        rwsFeignService.preload(preloadParam);
    }

    @Override
    public boolean isLive(String peerId) {
        Device currentDevice = this.getCurrentDevice(peerId);
        return StringUtils.equals(currentDevice.getStatus(), LocalConstant.DeviceStatus.LIVING);
    }

    @Override
    public Result<String> isDeviceExist(String oldPeerId, String newPeerId) {
        StringBuilder builder = new StringBuilder();
        MyDevice oldDevice = this.getDBDevice(oldPeerId);
        if (oldDevice == null) {
            builder.append(oldPeerId).append(",");
        }
        MyDevice newDevice = this.getDBDevice(newPeerId);
        if (newDevice == null) {
            builder.append(newPeerId);
        }
        if (StringUtils.isBlank(builder.toString())) {
            return ResultUtil.success();
        }
        return ResultUtil.error("101", "Device not exist", builder.toString());
    }

    @Override
    public Result<String> checkCopy(String oldPeerId, String newPeerId, String taskId) {
        // 1. Check ExternalReceiverRelation
        List<String> fullIds = externalReceiverRelationMapper.listFullIdsInPeerId1NotInPeerId2(oldPeerId, newPeerId);
        if (!CollectionUtils.isEmpty(fullIds)) {
            log.error("CheckCopyDevice copy ExternalReceiverRelation Receiver failed taskId:[{}] oldPeerId:[{}] newPeerId:[{}] old exist fullIds:[{}]", taskId, oldPeerId, newPeerId, fullIds);
            return ResultUtil.error("81101101","Copy Device ExternalReceiverRelation failed");
        }
        fullIds = externalReceiverRelationMapper.listFullIdsInPeerId1NotInPeerId2(oldPeerId + gridPack, newPeerId + gridPack);
        if (!CollectionUtils.isEmpty(fullIds)) {
            log.error("CheckCopyDevice copy ExternalReceiverRelation Grid Pack failed taskId:[{}] oldPeerId:[{}] newPeerId:[{}] old exist fullIds:[{}]", taskId, oldPeerId, newPeerId, fullIds);
            return ResultUtil.error("81101102","Copy Grid Pack ExternalReceiverRelation failed");
        }
        fullIds = externalReceiverRelationMapper.listFullIdsInPeerId1NotInPeerId2(oldPeerId + gridSdi, newPeerId + gridSdi);
        if (!CollectionUtils.isEmpty(fullIds)) {
            log.error("CheckCopyDevice copy ExternalReceiverRelation Grid Sdi failed taskId:[{}] oldPeerId:[{}] newPeerId:[{}] old exist fullIds:[{}]", taskId, oldPeerId, newPeerId, fullIds);
            return ResultUtil.error("81101103","Copy Grid Sdi ExternalReceiverRelation failed");
        }
        // 2. Check DeviceResoureRelation
        int gridCount = deviceResoureRelationMapper.countGridIdInPeerId1NotInPeerId2(oldPeerId, newPeerId);
        if (gridCount != 0) {
            log.error("CheckCopyDevice copy DeviceResoureRelation Receiver failed taskId:[{}] oldPeerId:[{}] newPeerId:[{}] old exist gridCount:[{}]", taskId, oldPeerId, newPeerId, gridCount);
            return ResultUtil.error("81101104","Copy Receiver DeviceResoureRelation failed");
        }
        int ridCount = deviceResoureRelationMapper.countRIdInPeerId1NotInPeerId2(oldPeerId, newPeerId, gridPack);
        if (ridCount != 0) {
            log.error("CheckCopyDevice copy DeviceResoureRelation Grid Pack failed taskId:[{}] oldPeerId:[{}] newPeerId:[{}] old exist ridCount:[{}]", taskId, oldPeerId, newPeerId, ridCount);
            return ResultUtil.error("81101105","Copy Grid Pack DeviceResoureRelation failed");
        }
        ridCount = deviceResoureRelationMapper.countRIdInPeerId1NotInPeerId2(oldPeerId, newPeerId, gridSdi);
        if (ridCount != 0) {
            log.error("CheckCopyDevice copy DeviceResoureRelation Grid Sdi failed taskId:[{}] oldPeerId:[{}] newPeerId:[{}] old exist ridCount:[{}]", taskId, oldPeerId, newPeerId, ridCount);
            return ResultUtil.error("81101106","Copy Grid Sdi DeviceResoureRelation failed");
        }

        // User check copy
        try {
            Result<String> userCheckResult = userFeignService.checkCopy(oldPeerId, newPeerId, taskId);
            if (!userCheckResult.assertSuccess()) {
                log.error("CheckCopyDevice copy call tvucc-user failed taskId:[{}] oldPeerId:[{}] newPeerId:[{}] result:[{}]", taskId, oldPeerId, newPeerId, userCheckResult);
                return userCheckResult;
            }
        } catch (Exception e) {
            log.error(e.toString(), e);
            log.error("CheckCopyDevice copy RPC tvucc-user failed taskId:[{}] oldPeerId:[{}] newPeerId:[{}]", taskId, oldPeerId, newPeerId);
            return ResultUtil.error("81101107", "tvucc-user check copy failed");
        }

        // Token check copy
        try {
            Result<String> tokenCheckResult = tokenFeignService.checkCopy(oldPeerId, newPeerId, taskId);
            if (!tokenCheckResult.assertSuccess()) {
                log.error("CheckCopyDevice copy call tvucc-token failed taskId:[{}] oldPeerId:[{}] newPeerId:[{}] result:[{}]", taskId, oldPeerId, newPeerId, tokenCheckResult);
                return tokenCheckResult;
            }
        } catch (Exception e) {
            log.error(e.toString(), e);
            log.error("CheckCopyDevice copy RPC tvucc-token failed taskId:[{}] oldPeerId:[{}] newPeerId:[{}]", taskId, oldPeerId, newPeerId);
            return ResultUtil.error("81101108", "tvucc-token check copy failed");
        }
        log.error("CheckCopyDevice success taskId:[{}] oldPeerId:[{}] newPeerId:[{}]", taskId, oldPeerId, newPeerId);
        return ResultUtil.success();
    }

    @Override
    @Transactional
    public Result<String> copyDevice(String oldPeerId, String newPeerId, String taskId) {
        oldPeerId = StringUtils.lowerCase(oldPeerId);
        newPeerId = StringUtils.lowerCase(newPeerId);
        log.error("Start copyDevice taskId:[{}] oldPeerId:[{}] newPeerId:[{}]", taskId, oldPeerId, newPeerId);
        // 1. 校验是否是同一个设备
        if (StringUtils.equalsIgnoreCase(oldPeerId, newPeerId)) {
            log.error("Start copyDevice failed taskId:[{}] oldPeerId:[{}] newPeerId:[{}]", taskId, oldPeerId, newPeerId);
            return ResultUtil.error("81101001", "Same device");
        }
        // 2. 校验设备存在
        MyDevice oldDevice = myDeviceService.getDeviceByPeerId(oldPeerId);
        if (oldDevice == null) {
            log.error("Start copyDevice failed Old device not exist taskId:[{}] oldPeerId:[{}] newPeerId:[{}]", taskId, oldPeerId, newPeerId);
            return ResultUtil.error("81101002", "Old device not exist");
        }
        MyDevice newDevice = myDeviceService.getDeviceByPeerId(newPeerId);
        if (newDevice == null) {
            log.error("Start copyDevice failed New device not exist taskId:[{}] oldPeerId:[{}] newPeerId:[{}]", taskId, oldPeerId, newPeerId);
            return ResultUtil.error("81101003", "New device not exist");
        }
        // 3. 校验设备是 R
        if (!LocalConstant.DeviceType.R.equals(oldDevice.getType())) {
            log.error("Start copyDevice failed Old device not R type:[{}] taskId:[{}] oldPeerId:[{}] newPeerId:[{}]", oldDevice.getType(), taskId, oldPeerId, newPeerId);
            return ResultUtil.error("81101004", "Old device not R");
        }
        if (!LocalConstant.DeviceType.R.equals(newDevice.getType())) {
            log.error("Start copyDevice failed New device not R type:[{}] taskId:[{}] oldPeerId:[{}] newPeerId:[{}]", oldDevice.getType(), taskId, oldPeerId, newPeerId);
            return ResultUtil.error("81101005", "New device not R");
        }

        // 1. Copy Device Metadata
        this.copyDeviceMetadata(oldPeerId, newPeerId);
        this.copyDeviceMetadata(oldPeerId + gridPack, newPeerId + gridPack);
        this.copyDeviceMetadata(oldPeerId + gridSdi, newPeerId + gridSdi);
        // 2. Copy ExternalReceiverRelation
        Set<String> rids = new HashSet<>();
        // copy ext-r 涉及到的 R
        externalReceiverRelationService.copyR(oldPeerId, newPeerId, taskId);
        // 3. Copy DeviceResoureRelation
        // copy x-r 涉及到的 R
        Set<String> rIdList2 = deviceResoureRelationService.copyR(oldPeerId, newPeerId, taskId);
        if (!CollectionUtils.isEmpty(rIdList2)) {
            rids.addAll(rIdList2);
        }
        // 4. 2和3之后通知 R 重新下发 Ext和X
        rids.add(newPeerId);
        for (String rid : rids) {
            deviceService.preloadExtXToR(newPeerId);
            log.error("Start copyDevice notify receiver preload taskId:[{}] oldPeerId:[{}] newPeerId:[{}] preloadRid:[{}]", taskId, oldPeerId, newPeerId, rid);
        }

        // 5. tvucc-user 复制 UserDevice BookmarkDevice
        try {
            Result<String> userResult = userFeignService.copyDevice(oldPeerId, newPeerId, taskId);
            log.error("Start copyDevice tvucc-user result taskId:[{}] oldPeerId:[{}] newPeerId:[{}] result:[{}]", taskId, oldPeerId, newPeerId, userResult);
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
        // 6. tvucc-token 复制 Token
        try {
            Result<String> tokenResult = tokenFeignService.copyDevice(oldPeerId, newPeerId, taskId);
            log.error("Start copyDevice tvucc-token result taskId:[{}] oldPeerId:[{}] newPeerId:[{}] result:[{}]", taskId, oldPeerId, newPeerId, tokenResult);
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
        return ResultUtil.success();
    }

    private void copyDeviceMetadata(String oldPeerId, String newPeerId){
        MyDevice oldDevice = myDeviceService.getDeviceByPeerId(oldPeerId);
        if (oldDevice == null) {
            return;
        }
        MyDevice newDevice = myDeviceService.getDeviceByPeerId(newPeerId);
        if (newDevice == null) {
            return;
        }
        // 1. Copy Device Metadata
        newDevice.setMetaData(oldDevice.getMetaData());
        myDeviceMapper.updateByPrimaryKey(newDevice);
    }

    @Override
    public Result<String> deleteDevice(String peerId, String taskId) {
        return null;
    }

    @Override
    public Result<String> listDeviceLocationByMultiIpOrPeerId(String ips,String peerIds,String mapType) {
        if(isProduct){
            return ResultUtil.success();
        }
        List<DeviceGeo> deviceGeoResultList = new ArrayList<>();

        String [] peerIdArr = peerIds.split(",");
        List<String> peerIdList = Arrays.asList(peerIdArr);
        if(peerIdList.size()>0){
            List<DeviceGeo>  deviceGeoLists = userFeignInterface.getDeviceGeoByPeerIds(peerIdList);
            if(deviceGeoLists.size()>0){
                deviceGeoResultList = deviceGeoLists.stream().filter(e ->e.getStatus().equals(2)).collect(Collectors.toList());
            }
        }
        String url=geoServiceUrl+"/Out/getGpsInfoByMultiIpOrPeerIdServlet";
        Map<String,String> paramMap = new HashMap<String,String >();
        paramMap.put("whiteListKey","tvu_geo_white_list_");
        if(!StringUtils.isEmpty(ips)){
            paramMap.put("ip",ips);
        }
        if(!StringUtils.isEmpty(peerIds)){
            paramMap.put("peerId",peerIds);
        }
        String body="";
//        String resultIp = HttpClientUtils.doPostByJsonParam(url,param);
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            // 以表单的方式提交
            HttpEntity<Map<String,String>> request = new HttpEntity<Map<String,String>>(paramMap, headers);
            log.error("==listDeviceLocationByMultiIpOrPeerId==param="+JSONObject.toJSONString(paramMap));

            ResponseEntity<String> responseEntity = restTemplate.postForEntity(url,request, String.class,paramMap);
            body = responseEntity.getBody();
        } catch (RestClientException e) {
            log.error("msg:{},e:{}",e.getMessage(),e);
            log.error("==listDeviceLocationByMultiIpOrPeerId==exception===",e);
        }
        log.error("==listDeviceLocationByMultiIpOrPeerId==="+body);
        JSONObject jsonObject = JSON.parseObject(body);
        if(jsonObject ==null){
            ResultUtil.success();
        }
        if(jsonObject !=null) {
            if (jsonObject.get("data") == null) {
                return ResultUtil.success("listDeviceLocationByMultiIpOrPeerId is null");
            }

            JSONArray dataJson = JSONArray.parseArray(jsonObject.get("data").toString());

            JSONArray relJson = new JSONArray();
            for (int j = 0; j < dataJson.size(); j++) {
                JSONObject arrJson = (JSONObject) dataJson.get(j);
                for (DeviceGeo deviceGeo : deviceGeoResultList) {
                    String peerId = deviceGeo.getPeerId();
                    if (peerId.toLowerCase().equals(arrJson.get("peerId").toString().toLowerCase()) && !"0,0".equals(deviceGeo.getManual())) {
                        arrJson.put("location", deviceGeo.getManual());
                        String locationName = "";
                        try {
                            Result<String> name = userFeignService.getGeoNameByLocation(deviceGeo.getManual());
                            locationName = name.getResult();
                        } catch (Exception e) {
                            log.error("userFeignService.getGeoNameByLocation Exception", e);
                        }
                        arrJson.put("address", locationName);//应该是查询geo获取geoname
                        continue;
                    }
                }

                //添加百度纠偏
                if ("baidu".equals(mapType) && arrJson.containsKey("location")) {
                    String position = arrJson.getString("location");
                    String[] geoInfoStr = position.split(",");
                    double[] geoInfo = GPSUtil.gcj02_To_Bd09(Double.valueOf(geoInfoStr[0]), Double.valueOf(geoInfoStr[1]));
                    position = geoInfo[0] + "," + geoInfo[1];
                    arrJson.put("location", position);
                }
                relJson.add(arrJson);
            }

            if (relJson.size() > 0) {
                jsonObject.put("data", relJson);
            }
        }
        return ResultUtil.success(JSON.toJSONString(jsonObject));
    }

    @Override
    public Result<String> listGPSByMultiPeerId(String peerIds) {
        String url = geoServiceUrl+"/Out/getGPSBypeeridAndTimestampServlet?peerid="+peerIds;
        String body="";
        try {
//            String resultPeers = HttpClientUtils.doGetNoParam(url);
            ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);
            body = responseEntity.getBody();
        } catch (Exception e) {
            log.error("msg:{},e:{}",e.getMessage(),e);
            log.error("==listGPSByMultiPeerId==exception===",e);
        }
        return ResultUtil.success(body);
    }

    @Override
    public Result<String> getMetadata(String peerId) throws Exception{
        String [] peerIdArr = peerId.split(",");
        List<String> peerIdList = Arrays.asList(peerIdArr);
        List<Device> listDevice = myDeviceMapper.listDevices(peerIdList);
        Device  device = new Device();
        if(listDevice!=null && listDevice.size()>0){
            device = listDevice.get(0);
        }
        return ResultUtil.success(device);
    }
    @Override
    public Result<String> getMetadataList(String peerId) throws Exception{
        String [] peerIdArr = peerId.split(",");
        List<String> peerIdList = Arrays.asList(peerIdArr);
        List<Device> listDevice = myDeviceMapper.listDevices(peerIdList);
        String jsonResualt = JsonUtil.toJsonStr(listDevice);
        return ResultUtil.success(jsonResualt);
    }

    @Override
    public void setToTpdsMemcache(String key, String value) {
        tpdsMemcacheClient.set(key,0,value);
    }

    @Override
    public boolean doubleCheckDeviceOffline(String peerId) {
        if (StringUtils.isBlank(peerId)) {
            return true;
        }
        Device device = deviceService.getCurrentDevice(peerId);
        if (device == null || LocalConstant.DeviceStatus.OFFLINE.equalsIgnoreCase(device.getStatus())) {
            device = deviceService.getCurrentDevice(peerId);
        }
        return device == null || LocalConstant.DeviceStatus.OFFLINE.equalsIgnoreCase(device.getStatus());
    }

    @Override
    public void globalUpdateDeviceName(String peerId, String name, String session) {
        Device device = deviceService.getCurrentDevice(peerId);
        if (device == null) {
            log.error("globalUpdateDeviceName failed, device not exist in cc peerId:{} name:{}", peerId, name);
            ServerException.Exception(ResultConstant.Device.DEVICE_NOT_EXIST);
        }

        String type = device.getType();
        if (!LocalConstant.DeviceType.T.equals(type)) {
            // 如果不是 T，那么调用 TPC 修改设备名字
            log.error("globalUpdateDeviceName device not T, update deviceName from TPC peerId:{} name:{}", peerId, name);
            Result<String> result = this.updateDeviceName(peerId, name, type, session);
            if (!result.assertSuccess()) {
                log.error("globalUpdateDeviceName device not T, update failed, update deviceName from TPC peerId:{} name:{} result:{}", peerId, name, result);
                ServerException.Exception(result);
            }
            log.error("globalUpdateDeviceName device not T, update success, update deviceName from TPC peerId:{} name:{}", peerId, name);
            return;
        }

        if (!CollectionUtils.isEmpty(PtsPrs.getPts())) {
            PST pst = PtsPrs.getPts().get(peerId);
            if (pst != null) {
                log.error("globalUpdateDeviceName device is T, exist in PeerService, update deviceName from TPC peerId:{} name:{}", peerId, name);
                // 设备在 PeerService 存在，调用 TPC 修改设备名字
                Result<String> result = this.updateDeviceName(peerId, name, type, session);
                if (!result.assertSuccess()) {
                    log.error("globalUpdateDeviceName device is T, update failed, exist in PeerService, update deviceName from TPC peerId:{} name:{} result:{}", peerId, name, result);
                    ServerException.Exception(result);
                    log.error("globalUpdateDeviceName device is T, update success, exist in PeerService, update deviceName from TPC peerId:{} name:{}", peerId, name);
                }
            }
            log.error("globalUpdateDeviceName device is T, update deviceName from Token peerId:{} name:{}", peerId, name);
            Result<String> result = this.updateAnywhereName(peerId, name, session);
            if (!result.assertSuccess()) {
                log.error("globalUpdateDeviceName device is T, update failed, update deviceName from Token peerId:{} name:{} result:{}", peerId, name, result);
                ServerException.Exception(result);
                log.error("globalUpdateDeviceName device is T, update success, update deviceName from Token peerId:{} name:{}", peerId, name);

            }
        }
    }

    @Override
    public List<Device> listDeviceByExample(Device device) {
        return myDeviceMapper.listDeviceByExample(device);
    }

    @Override
    public Result<String> getRSourceTypeList(String rid) {
        return null;
    }

    @Override
    public PageInfo<ExtendExternal> getGLinkList(SearchDeviceParam searchDeviceParam) {
        List<ExtendExternal> extendExternalList = null;
        try {
            extendExternalList = extendExternalMapper.selectExtendExternal(searchDeviceParam.getRid(),searchDeviceParam.getCondition(),"GLink");
        } catch (Exception e) {
            log.error("msg:{},e:{}",e.getMessage(),e);
        }
        if (searchDeviceParam.isSyncWebR() && StringUtils.isNotEmpty(searchDeviceParam.getRid())) {
            try {
                //同步webR里面的gLink
                List<ExtendExternal> gLinkFromWebR = this.getGLinkFromWebR(searchDeviceParam.getRid());
                if (!CollectionUtils.isEmpty(gLinkFromWebR) && StringUtils.isNotEmpty(searchDeviceParam.getCondition())) {
                    gLinkFromWebR = gLinkFromWebR.stream().filter(s -> StringUtils.containsIgnoreCase(s.getName(), searchDeviceParam.getCondition())
                            || StringUtils.containsIgnoreCase(s.getPeerId(), searchDeviceParam.getCondition())).collect(Collectors.toList());
                }
                if (!CollectionUtils.isEmpty(gLinkFromWebR)) {
                    if (!CollectionUtils.isEmpty(extendExternalList)) {
                        List<String> peerIds = extendExternalList.stream().map(s->s.getPeerId().toLowerCase()).collect(Collectors.toList());
                        List<ExtendExternal> notExists = gLinkFromWebR.stream().filter(s -> !peerIds.contains(s.getPeerId().toLowerCase())).collect(Collectors.toList());
                        extendExternalList.addAll(notExists);
                    }else {
                        extendExternalList = gLinkFromWebR;
                    }
                }
            } catch (Exception e) {
                log.error("getGLinkList>>>>>getGLinkListFromWebRException,rid:[{}],e:[{}]", searchDeviceParam.getRid(), e);
            }
        }
        if (CollectionUtils.isEmpty(extendExternalList)) {
            return new PageInfo<>();
        }
        PageInfo<ExtendExternal> pageInfo = new PageInfo<ExtendExternal>();
        pageInfo.setTotal(extendExternalList.size());
        if (searchDeviceParam.getPageNum() <= 0 || searchDeviceParam.getPageSize() <= 0) {
            pageInfo.setPageNum(1);
            pageInfo.setPageSize(extendExternalList.size());
            pageInfo.setList(extendExternalList);
            return pageInfo;
        }
        pageInfo.setPageNum(searchDeviceParam.getPageNum());
        pageInfo.setPageSize(searchDeviceParam.getPageSize());
        int startIndex = searchDeviceParam.getPageSize() * (searchDeviceParam.getPageNum() - 1);
        if (startIndex == 0) {
            extendExternalList = extendExternalList.stream().limit(searchDeviceParam.getPageSize()).collect(Collectors.toList());
        } else {
            extendExternalList = extendExternalList.stream().skip(startIndex).limit(searchDeviceParam.getPageSize()).collect(Collectors.toList());
        }
        pageInfo.setList(extendExternalList);
        return pageInfo;
    }

    @Override
    public PageInfo<ExtendExternal> getRTILList(SearchDeviceParam searchDeviceParam) {

        PageHelper.startPage(searchDeviceParam.getPageNum(),searchDeviceParam.getPageSize());
        List<ExtendExternal> extendExternalList = null;
        try {
            extendExternalList = extendExternalMapper.selectExtendExternal(searchDeviceParam.getRid(),searchDeviceParam.getCondition(),"RTIL");
        } catch (Exception e) {
            log.error("msg:{},e:{}",e.getMessage(),e);
        }
        PageInfo<ExtendExternal> pageInfo = new PageInfo<ExtendExternal>(extendExternalList);
        return pageInfo;
    }

    // Receiver 上线，通知 token 服务，如果 R ip 发生变化，重新下发配对信息
    @Override
    public void notifyTokenReceiverOnline(String message) throws IOException {
        // 通知 PageWebsocket 设备变化
        JsonNode jsonNode = MyUtil.MAPPER.readTree(message);
        if (!jsonNode.has("peerId")) {
            log.error("notifyTokenReceiverOnline failed message not contain peerId message:{}", message);
            return;
        }
        if (!jsonNode.has("data")) {
            log.error("notifyTokenReceiverOnline failed message not contain data message:{}", message);
            return;
        }
        JsonNode data = jsonNode.get("data");

        if (data.has("status")) {
            JsonNode statusChange = data.get("status");
            if (statusChange.has("old") && statusChange.has("new")) {
                String oldStatus = statusChange.get("old").asText();
                String newStatus = statusChange.get("new").asText();

                if (LocalConstant.DeviceStatus.OFFLINE.equals(oldStatus) && LocalConstant.DeviceStatus.ONLINE.equals(newStatus)) {
                    String peerId = jsonNode.get("peerId").asText();
                    Device device = deviceService.getCurrentDevice(peerId);
                    if (device != null && LocalConstant.DeviceType.R.equals(device.getType())) {
                        log.error("notifyTokenReceiverOnline status from offline to online call tvucc-token rStatusChangeCheckRPair message:{}", message);
                        tokenFeignService.rStatusChangeCheckRPair(peerId);
                        return;
                    } else {
                        log.info("notifyTokenReceiverOnline check status failed device not R message:{} device:{}", message, device);
                    }
                } else {
                    log.info("notifyTokenReceiverOnline check status failed message:{}", message);
                }
            } else {
                log.error("notifyTokenReceiverOnline check status failed, message:{}", message);
            }
        }
        if (data.has("ip")) {
            String peerId = jsonNode.get("peerId").asText();
            Device device = deviceService.getCurrentDevice(peerId);
            if (device != null && LocalConstant.DeviceType.R.equals(device.getType())) {
                log.error("notifyTokenReceiverOnline ip changed call tvucc-token rStatusChangeCheckRPair, message:{}", message);
                tokenFeignService.rStatusChangeCheckRPair(peerId);
                return;
            } else {
                log.error("notifyTokenReceiverOnline ip changed but device not R, message:{}", message);
            }
        }

    }

    @Override
    public PageInfo<NotConnectR> listNotConnectR(int pageNum, int pageSize) {
        List<String> types = new ArrayList<>();
        types.add(LocalConstant.DeviceType.R);
        List<String> rids = myDeviceMapper.listPeerIdByTypes(types);
        if (CollectionUtils.isEmpty(rids)) {
            return new PageInfo<>(new ArrayList<>());
        }
        rids = rids.stream().filter(i -> !i.startsWith(LocalConstant.PP_R_PREFIX)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(rids)) {
            return new PageInfo<>(new ArrayList<>());
        }

        List<String> notConnectRids = new ArrayList<>();
        List<List<String>> ridsList = MyUtil.stepPage(rids, listNotConnectRStepNum);
        for (List<String> stepRids : ridsList) {
            List<String> peerIds = this.listNotConnectR(stepRids);
            notConnectRids.addAll(peerIds);
        }

        List<NotConnectR> result = new ArrayList<>();
        List<Device> devices = this.listCurrentDevice(notConnectRids);
        if (CollectionUtils.isEmpty(devices)) {
            return new PageInfo<>(new ArrayList<>());
        }
        for (Device device : devices) {
            result.add(JsonUtil.convertValue(device, NotConnectR.class));
        }

        result = result.stream().sorted(Comparator.comparing(NotConnectR::getVersion).reversed()).collect(Collectors.toList());

        PageInfo<NotConnectR> pageInfo = MyUtil.packagePageInfo(result, pageNum, pageSize);
        return pageInfo;
    }



    @Override
    public void initReceiverUploadParam(String peerId) {
        Map<String, String> map = new HashMap<>();
        map.put("AccessKey", s3UploadAccessKey);
        map.put("SecretKey", s3UploadAccessSecret);
        map.put("EndPoint", s3UploadRegion);
        map.put("BucketName", s3UploadBucket);

        CommandParam commandParam = new CommandParam();
        commandParam.setRid(peerId.toLowerCase());
        commandParam.setCategoryId(receiverS3UploadCategoryId);
        commandParam.setOperationType(receiverS3UploadOperationType);
        try {
            commandParam.setData(JsonUtil.toJsonStr(map));
        } catch (IOException e) {
            log.error(e.toString(), e);
        }
        ThreadPoolUtil.SERVICETHREADPOOL.execute(() -> {
            Result<String> result = null;
            for (int i = 0; i < initReceiverUploadParamRetryTimes; i++) {
                log.error("initReceiverUploadParam param:[{}] result:[{}]", commandParam, result);
                result = rwsFeignService.command(commandParam);
                if (result.assertSuccess()) {
                    String content = result.getResult();
                    if (StringUtils.contains(content, "0x0")) {
                        log.error("initReceiverUploadParam success peerId:[{}]", peerId);
                        return;
                    }
                }
            }
        });
    }

    @Override
    public List<Device> listReceiverGrid(String rid) {
        List<Device> list = new ArrayList<>();
        Device pack = this.getCurrentDevice(rid + gridPack);
        if (pack != null) {
            list.add(pack);
        }
        Device sdi = this.getCurrentDevice(rid + gridSdi);
        if (sdi != null) {
            list.add(sdi);
        }
        return list;
    }

    @Override
    public Map<String, List<Device>> listReceiversGrid(List<String> rids) {
        if (CollectionUtils.isEmpty(rids)) {
            return new HashMap<>();
        }
        Map<String, List<Device>> map = new HashMap<>();
        for (String rid : rids) {
            List<Device> devices = this.listReceiverGrid(rid);
            map.put(rid, devices);
        }
        return map;
    }

    @Value("${getDeviceIpPort.await.time:10}")
    private int getDeviceIpPortAwaitTime;

    @Override
    public List<DeviceIpPort> getDeviceIpPort(List<String> pids) throws ExecutionException, InterruptedException {
        if (CollectionUtils.isEmpty(pids)) {
            return new ArrayList<>(0);
        }
        CountDownLatch latch = new CountDownLatch(pids.size());
      //  List<DeviceIpPort> list = new ArrayList<>();

        CopyOnWriteArrayList<DeviceIpPort> resultList = new CopyOnWriteArrayList<>();
        for (String pid : pids) {
            GetDeviceIpPortThread thread = new GetDeviceIpPortThread(latch, pid, resultList);
            ThreadPoolUtil.SERVICETHREADPOOL.execute(thread);
        }
//        List<Future<DeviceIpPort>> resultList = new ArrayList<>();
//        for (String pid : pids) {
//            Future<DeviceIpPort> submit = ThreadPoolUtil.serviceThreadPool.submit(() -> {
//                return this.getDeviceIpPort(pid);
//            });
//            resultList.add(submit);
////            DeviceIpPort deviceIpPort = getDeviceIpPort(pid);
////            list.add(deviceIpPort);
//        }
//        for (Future<DeviceIpPort> future : resultList) {
//            list.add(future.get());
//        }
        boolean await = latch.await(getDeviceIpPortAwaitTime, TimeUnit.SECONDS);
        log.error("latch:-->",await);

        return resultList;
    }


    class GetDeviceIpPortThread extends Thread {

        CountDownLatch latch;
        String peerId;
        CopyOnWriteArrayList<DeviceIpPort> list;

         GetDeviceIpPortThread(CountDownLatch latch, String peerId, CopyOnWriteArrayList<DeviceIpPort> list) {
            this.latch = latch;
            this.peerId = peerId;
            this.list = list;
        }
        
        @Override
        public void run() {
            DeviceIpPort deviceIpPort = getDeviceIpPort(peerId);
            if (deviceIpPort != null) {
                list.add(deviceIpPort);
            }
            latch.countDown();
        }
    }


    private DeviceIpPort getDeviceIpPort(String peerId) {
        try {
            if ( StringUtils.isEmpty(peerId) ) {
                return null;
            }
            peerId = peerId.toLowerCase();
            DeviceIpPort deviceIpPort = new DeviceIpPort();
            Device device = getCurrentDevice(peerId);
            if ( device != null ) {
                deviceIpPort.setPid(peerId);
                deviceIpPort.setExternalIp(device.getIp());
                if ( StringUtils.isNotEmpty(device.getPort()) ) {
                    Integer externalPort = Integer.valueOf(device.getPort().trim());
                    deviceIpPort.setExternalPort(externalPort);
                }

                CommandParam commandParam = new CommandParam();
                commandParam.setRid(peerId);
                commandParam.setCategoryId(ReceiverCommandConstant.CategoryId.PACK_RECEIVER_CORE);
                commandParam.setOperationType(ReceiverCommandConstant.OperationType.QUERY_RECEIVER_INFO);
                Result<String> command = rwsFeignService.command(commandParam);
                log.error("getDeviceIpPort peerId:[{}] command:[{}]", peerId, command);
                if (command.assertSuccess()) {
                    String result = command.getResult();
                    JsonNode jsonNode = MyUtil.MAPPER.readTree(result);
                    if (jsonNode.has("NginxLocalPort")) {
                        int nginxLocalPort = jsonNode.get("NginxLocalPort").asInt();
                        deviceIpPort.setLocalPort(nginxLocalPort);
                    }
                    if (jsonNode.has("LocalIPAddresses")) {
                        JsonNode localIPAddresses = jsonNode.get("LocalIPAddresses");
                        List<String> lockIpList = new ArrayList<>();
                        for (JsonNode localIPAddress : localIPAddresses) {
                            String ip = localIPAddress.asText();
                            lockIpList.add(ip);
                        }
                        deviceIpPort.setLocalIp(lockIpList);
                    }
                }
                return deviceIpPort;
            }
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
        return null;
    }

    private List<String> listNotConnectR(List<String> rids) {
        if (CollectionUtils.isEmpty(rids)) {
            return new ArrayList<>(0);
        }
        List<Device> receivers = this.listCurrentDevice(rids);
        if (CollectionUtils.isEmpty(receivers)) {
            return new ArrayList<>(0);
        }
        receivers = receivers.stream().filter(r -> !LocalConstant.DeviceStatus.OFFLINE.equals(r.getStatus())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(receivers)) {
            return new ArrayList<>(0);
        }
        List<String> onlinePeerIds = receivers.stream().map(Device::getPeerId).collect(Collectors.toList());
        List<String> connectCCR = rwsFeignService.filterConnectCCR(onlinePeerIds);
        onlinePeerIds.removeAll(connectCCR);
        return onlinePeerIds;
    }

    /**
     *
     * @return String
     */
    public String getSession(){
        Result<String> result = userFeignService.getSuperAdminSession();
        if (result.assertSuccess()) {
            return result.getResult();
        }
        throw new ServerException(ResultConstant.User.GET_ADMIN_SESSION_FAILED);
    }

    private String packageTypeCondition(SearchDeviceParam param) {
        StringBuilder typeString = new StringBuilder();
        if (param.isReceiver()) {
            typeString.append(" OR d.type = 'R'");
        }

        if (param.isPack() || param.isAnywhere()) {
            typeString.append(" OR ( ");
            typeString.append(" d.type = 'T'");
            if (!param.isPack()) {
                typeString.append(" AND d.platform != '' AND d.platform >= 10 AND d.platform <= 14");
            }
            if (!param.isAnywhere()) {
                typeString.append(" AND d.platform != '' AND (d.platform < 10 OR d.platform > 14)");
            }
            typeString.append(")");
        }
        if (param.isGridPack() || param.isGridSdi()) {
            typeString.append(" OR (");
            typeString.append(" d.type = 'X'");
            if (!param.isGridPack()) {
                typeString.append(" AND d.peer_id LIKE '%0000000000000002'");
            }
            if (!param.isGridSdi()) {
                typeString.append(" AND d.peer_id LIKE '%0000000000000001'");
            }
            typeString.append(" )");
        }
        if (param.isExt()) {
            typeString.append(" OR d.type in ('Ext','YouTube','SMPTE2022')");
        }
        typeString.append(" )");
        String result = typeString.toString().substring(3);
        return "(" + result;
    }

    /**
     *
     * @param tid tid
     * @param name name
     * @param session session
     * @return String
     * @throws ClientProtocolException 编译异常
     * @throws IOException 编译异常
     */
    //update anywhere name from old cc
    public String modifyName(String tid, String name, String session) throws ClientProtocolException, IOException {
        Device t =  deviceService.getCurrentDevice(tid);
        if(t==null){
            return "device no exist";
        }
        DeviceSy d =new DeviceSy();
        if(StringUtils.isNotEmpty(t.getAvailable())){
            d.setAvailable(Integer.valueOf(t.getAvailable()));
        }
        if(StringUtils.isNotEmpty(t.getPeerId())){
            d.setDeviceId(t.getPeerId());
        }
/*    	if(StringUtils.isNotEmpty(t.getName())){
    		d.setDeviceName(t.getName());
    	}*/
        if(StringUtils.isNotEmpty(t.getType())){
            d.setDeviceType(t.getType());
        }
        if(StringUtils.isNotEmpty(t.getStatus())){
            d.setStatus(t.getStatus());
        }
        if(StringUtils.isNotEmpty(t.getIsRelay())){
            d.setStatus(t.getStatus());
        }
        if(StringUtils.isNotEmpty(t.getPlatform())){
            d.setPlatform(t.getPlatform());;
        }
        if(StringUtils.isNotEmpty(t.getRemark())){
            d.setRemark(t.getRemark());;
        }
        if(StringUtils.isNotEmpty(t.getVersion())){
            d.setVersion(t.getVersion());
        }
        if(StringUtils.isNotEmpty(t.getIp())){
            d.setIp(t.getIp());
        }
        if(StringUtils.isNotEmpty(t.getPort())){
            d.setPort(t.getPort());
        }
        if(StringUtils.isNotEmpty(t.getTimeStamp())){
            d.setTimes(t.getTimeStamp());
        }
        if(StringUtils.isNotEmpty(t.getTimes())){
            d.setTimes(t.getTimes());
        }
        if(StringUtils.isNotEmpty(t.getLivePeerId())){
            d.setLivePeerId(t.getLivePeerId());
        }
        if(StringUtils.isNotEmpty(t.getUrl())){
            d.setUrl(t.getUrl());
        }
        if(StringUtils.isNotEmpty(t.getResourceId())){
            d.setResourceId(t.getResourceId());
        }
        if(StringUtils.isNotEmpty(t.getBuild())){
            d.setBuild(t.getBuild());
        }
        if(StringUtils.isNotEmpty(t.getLivePeerName())){
            d.setLivePeerName(t.getLivePeerName());
        }
/*     	if(StringUtils.isNotEmpty(t.getPassword())){
    		d.setPassword(t.getPassword());
    	}*/
        log.error("before modifyName to device name:===="+name);
        d.setDeviceName(URLDecoder.decode(name,"utf8"));
        d.setPassword("123");
        //String device = JSON.toString(t);
        String device = JsonUtil.toJsonStr(d);
        Map<String, String> params = new HashMap<>();
        params.put("device", device);
        params.put("pwd", "123");
        params.put("session", session);
        String url = userservice + "/main/UpdateDevice";
        if (!StringUtils.startsWith(url, "http://")) {
            url = "http://" + url;
        }
        log.error("after modifyName to DEVICE name:====="+name);
        log.error("Send modifyName to UserServer url:{}", url);
        log.error("Send modifyName to UserServer url session:{}", session);
        String httpResult = "";
        try {
//            HttpHeaders httpHeaders = new HttpHeaders();
//            httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

//            HttpEntity<Map<String, String>> httpEntity = new HttpEntity<>(params, httpHeaders);
////            ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, httpEntity, String.class);
//            ResponseEntity<String> responseEntitys = restTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class);
            httpResult =  doPost(url,params,"UTF-8");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            log.error("main/UpdateDevice is error  ,e : [{}]" ,e);
            log.error("msg:{},e:{}",e.getMessage(),e);
        }
        log.error("tid:"+tid+  "modifyName msg from UserServer result:{}", httpResult);
        return httpResult;
    }

    /**
     *
     * @param url url
     * @param map map
     * @param charset charset
     * @return String
     * @throws Exception 编译异常
     */
    public static String doPost(String url, Map<String,String> map, String charset) throws Exception{
        CloseableHttpClient httpClient = null;
        HttpPost httpPost = null;
        String result = null;

        httpClient = HttpClients.createDefault();
        httpPost = new HttpPost(url);
        httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
        //设置参数
        List<NameValuePair> list = new ArrayList<NameValuePair>();
        Iterator iterator = map.entrySet().iterator();
        while(iterator.hasNext()){
            Map.Entry<String,String> elem = (Map.Entry<String, String>) iterator.next();
            list.add(new BasicNameValuePair(elem.getKey(),elem.getValue()));
        }
        if(list.size() > 0){
            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list,charset);
            httpPost.setEntity(entity);
        }
        HttpResponse response = httpClient.execute(httpPost);
        if(response != null){
            org.apache.http.HttpEntity resEntity = response.getEntity();
            if(resEntity != null){
                result = EntityUtils.toString(resEntity,charset);
            }
        }
        return result;
    }

    /**
     *
     * @param name name
     * @param tId tId
     * @param session session
     * @return PackTokenResult
     */
    public PackTokenResult modifyPackName(String name, String tId, String session) {
        PackTokenResult item = new PackTokenResult();
        List<Map<String, String>> tRMapList = new ArrayList<Map<String, String>>();
        Map<String, PST> pts = PtsPrs.getPts();
        //设备是否存在TCP中，存在则调用TPC修改,不存在则说明设备时Token配对
        if (!pts.containsKey(tId.toLowerCase())) {
            // 获取所有跟T配对的R
            Set<String> list = tokenFeignService.listTokenTPairedR(tId);
            if (list != null && list.size() > 0) {
                for (String rid : list) {
                    if (StringUtils.isNotBlank(rid)) {
                        Long expireTime = getMaxPairExpireTime(rid, tId);
                        // set the longer time
                        if (expireTime != null) {
                            Map<String, String> map = new HashMap<>();
                            map.put("rId", rid);
                            map.put("tId", tId);
                            map.put("validtime", expireTime - System.currentTimeMillis() + "");
                            map.put("name", name);
                            tRMapList.add(map);
                        }
                    }
                }
                try {
                    if (tRMapList.size() > 0) {
                        // 刪除T所有的配對
                        log.error("========start remove all pair=========");
                        UpdateTokenCodeParam updateTokenCodeParam = new UpdateTokenCodeParam();
                        updateTokenCodeParam.setRemovePairList(tRMapList);
                        Result<Object> result = tokenFeignService.removePair(updateTokenCodeParam);
                        if (!StringUtils.equals(result.getErrorCode(),"0x0")) {
                            item.setErrorCode("0x3");
                            item.setErrorInfo("remover pair failure!");
                            return item;
                        }
                        log.error("======== remove all pair result========="+result);
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    log.error(" remove all pair is error,e :[{}]"+e);
                }

                try {

                    if (tRMapList.size() > 0) {
                        // 添加配對
                        log.error("========start add all pair=========");
                        UpdateTokenCodeParam updateTokenCodeParam = new UpdateTokenCodeParam();
                        updateTokenCodeParam.setAddPairList(tRMapList);
                        updateTokenCodeParam.setRemovePairList(new ArrayList<>());
                        Result<Object>  result = tokenFeignService.addPair(updateTokenCodeParam);
                        if (!"0x0".equals(result.getErrorCode())) {
                            item.setErrorCode("0x4");
                            item.setErrorInfo("add pair failure!");
                            //modifyResult.add(item);
                            return item;
                        } else {
                            log.error("======== add all pair result=========" + result + "========start synchronized userservice======");
                            String rusult = modifyName(tId, name, session);
                            if (rusult.contains("Success")) {
                                log.error("======== synchronized userservice result======" + rusult);
                            } else {
                                item.setErrorCode("0x5");
                                item.setErrorInfo(rusult);
                                //modifyResult.add(item);
                                return item;
                            }
                        }
                    }
                } catch (Exception e) {
                    log.error("addToken is error",e);
                }
            } else {
                //不存在配對，調用us接口修改名稱
                String rusult = "";
                try {
                    rusult = modifyName(tId, name, session);
                    if (rusult.contains("Success")) {
                        log.error("======== synchronized userservice result======" + rusult);
                    } else {
                        item.setErrorCode("0x5");
                        item.setErrorInfo(rusult);
                        return item;
                    }
                } catch (IOException e) {
                    log.error("======== synchronized userservice error====== ,e: [{}]" , e);
                }
            }
        } else {
            String updateDeviceNamebyTpc = updateDeviceName(tId.toLowerCase(), name, "T",session).getResult();
            log.error(">>>>>>>>invoke tpc get updateDeviceNamebyTpc:"+updateDeviceNamebyTpc);
            Map<String, String> result = null;
            try {
                result = JsonUtil.toObject(updateDeviceNamebyTpc, Map.class);
            } catch (Exception e) {
                log.error(">>>>>> tpc get updateDeviceNamebyTpc is error e : [{}]",e);
            }
            if(  result!=null && !StringUtils.equals("0x0",result.get("errorCode"))){
                item.setErrorCode("0x5");
                //调用tpc失败
                if(StringUtils.isEmpty(updateDeviceNamebyTpc)){
                    item.setErrorInfo("failed to call TPC to modify name!");
                }else{
                    Map mapper = null;
                    try {
                         mapper = JsonUtil.toObject(updateDeviceNamebyTpc,Map.class);
                    } catch (IOException e) {
                        log.error(e.getMessage(),e);
                    }
                    if(mapper !=null){
                        Object errorMsg = mapper.get("errorMsg");
                        if(errorMsg == null){
                            item.setErrorInfo("failed to call TPC to modify name!");
                        }else{
                            item.setErrorInfo(errorMsg.toString());
                        }
                    }
                }
                return item;
            }
        }
        item.setErrorCode("0x0");
        item.setErrorInfo("Success");
        //modifyResult.add(item);
        return item;
    }
    private Long getMaxPairExpireTime(String rId, String tId) {
        Long expireTime = 0L;
        //  List<TokenCodePo> list=new ArrayList<>();
        try {
            log.error("tokenFeignService.listCCPairTokenCode rid" + rId + "===tId==" + tId);
            List<TokenCodePo> list = tokenFeignService.listCCPairTokenCode(rId, tId);
            log.error("tokenFeignService.listCCPairTokenCode" + JsonUtil.toJsonStr(list));
            if (list != null && list.size() > 0) {
                for (TokenCodePo tokenCode : list) {
                    if (expireTime < tokenCode.getExpireTime()) {
                        expireTime = tokenCode.getExpireTime();
                    }
                }
                return expireTime;
            }
        } catch (IOException e) {
            log.error("listCCPairTokenCode Eexception", e);
        }
        log.info("Get Pair Expire Time null");
        return null;
    }

    @Override
    public List<Device> getExtFromWebR(String rid) {
        try {
            String extList = new GetAllPeerListByFiltersParam()
                    .getDeviceListString(1, 9999, LocalConstant.STRING_EXTERNAL_PEER_MANAGER);
            CommandParam extCommandParam = new CommandParam(rid, ReceiverCommandConstant.CategoryId.WEBR_SOURCE_TYPE,
                    ReceiverCommandConstant.OperationType.STOP_MUTE_VIDEO, extList);
            Result<String> extResult = rwsFeignService.command(extCommandParam);
            if (extResult.assertSuccess()) {
                return this.conversionWebRDeviceToDevice(extResult.getResult(), rid);
            }
            log.error("getExtFromWebR>>>>>>>getExt From WebR Failed,rid:[{}],result:[{}]", rid, extResult);
        } catch (Exception e) {
            log.error("getExtFromWebR>>>>>>>getExt From WebR Exception,rid:[{}],e:[{}]", rid, e);
        }
        return new ArrayList<>();
    }

    @Override
    public List<Device> getLocalSDIFromWebR(String rid) {
        try {
            String localSDIList = new GetAllPeerListByFiltersParam()
                    .getDeviceListString(1, 9999, LocalConstant.STRING_LOCAL_SDI_PEER_MANAGER);
            CommandParam localSDICommandParam = new CommandParam(rid, ReceiverCommandConstant.CategoryId.WEBR_SOURCE_TYPE,
                    ReceiverCommandConstant.OperationType.STOP_MUTE_VIDEO, localSDIList);
            Result<String> localSDIResult = rwsFeignService.command(localSDICommandParam);
            if (localSDIResult.assertSuccess()) {
                return this.conversionWebRDeviceToDevice(localSDIResult.getResult(), rid);
            }
            log.error("getLocalSDIFromWebR>>>>>>>getLocalSDI From WebR Failed,rid:[{}],result:[{}]", rid, localSDIResult);
        } catch (Exception e) {
            log.error("getLocalSDIFromWebR>>>>>>>getLocalSDI From WebR Exception,rid:[{}],e:[{}]", rid, e);
        }
        return new ArrayList<>();
    }

    @Override
    public List<ExtendExternal> getGLinkFromWebR(String rid) {
        try {
            String gLinkList = new GetAllPeerListByFiltersParam()
                    .getDeviceListString(1, 9999, LocalConstant.STRING_GLINK_PEER_MANAGER);
            CommandParam gLinkCommandParam = new CommandParam(rid, ReceiverCommandConstant.CategoryId.WEBR_SOURCE_TYPE,
                    ReceiverCommandConstant.OperationType.STOP_MUTE_VIDEO, gLinkList);
            Result<String> gLinkResult = rwsFeignService.command(gLinkCommandParam);
            if (gLinkResult.assertSuccess()) {
                return  (List<ExtendExternal>)this.conversionWebRDeviceToDevice(gLinkResult.getResult(), rid);
            }
            log.error("getGLinkFromWebR>>>>>>>getGLink From WebR Failed,rid:[{}],result:[{}]", rid, gLinkResult);
        } catch (Exception e) {
            log.error("getGLinkFromWebR>>>>>>>getGLink From WebR Exception,rid:[{}],e:[{}]", rid, e);
        }
        return new ArrayList<>();
    }

    @Override
    public List<Device> listReceiverByIpIsNotNull() {
        return myDeviceMapper.listReceiverByIpIsNotNull();
    }

    @Override
    public List<SlotVo> listLocalIp(String peerId) throws Exception{
        Device device = deviceService.getCurrentDevice(peerId);
        if (device == null) {
            throw new ServerException(ResultConstant.Device.DEVICE_NOT_EXIST);
        }
        if (!StringUtils.equalsIgnoreCase(device.getStatus(), "1") && !StringUtils.equalsIgnoreCase(device.getStatus(), "2")) {
            throw new ServerException(ResultConstant.Device.R_NOT_LIVING_AND_NOT_ONLINE);
        }
        List<SlotVo> slotVos = new ArrayList<>();
        String result = stringRedisTemplate.opsForValue().get(detailInfo + peerId.toLowerCase());
        if (StringUtils.isNotEmpty(result)) {
            ObjectMapper resultMapper = new ObjectMapper();
            resultMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
            T t = resultMapper.readValue(result, T.class);
            if (t != null) {
                List<T.TIME> timeList = t.getTIME();
                int timeListSize = timeList.size();
                if (timeListSize > 0) {
                    List<T.TIME.SLOT> slots = timeList.get(timeListSize - 1).getSLOT();
                    if (!CollectionUtils.isEmpty(slots)) {
                        slots.forEach(slot -> {
                            SlotVo slotVo = new SlotVo()
                                    .setSlotId(slot.getID())
                                    .setIp(slot.getIP())
                                    .setType(slot.getTYPE())
                                    .setName(slot.getNAME())
                                    .setCops(slot.getCops());
                            slotVos.add(slotVo);
                        });
                    }
                }
            }
        }
        if (CollectionUtils.isEmpty(slotVos)) {
            SlotVo slotVo = new SlotVo()
                    .setType("Default")
                    .setIp("0.0.0.0")
                    .setSlotId("")
                    .setCops("")
                    .setName("");
            slotVos.add(slotVo);
        }
        return slotVos;
    }

    @Override
    public int synGridSlug(List<SlugInfo> list) {
        return myDeviceMapper.synGridSlug(list);
    }

    @Override
    public int updateMetadata(String peerId, String slug) {
        if (StringUtils.isBlank(peerId)){
            return 0;
        }
        return myDeviceMapper.updateMetadata(peerId, slug);
    }

    /**
     * 将从webR下的device转为device
     * @param message
     * @return
     */
    private List conversionWebRDeviceToDevice(String message, String rid) {
        try {
            if (StringUtils.isEmpty(message)) {
                log.error("conversionType111>>>>>date is empty,message:[{}]", message);
                return null;
            }
            List<Map> deviceByFilterVos = JsonUtil.toObject(message, List.class);
            if (CollectionUtils.isEmpty(deviceByFilterVos) || deviceByFilterVos.get(0) == null) {
                log.error("conversionType111>>>>>>device is empty,message:[{}]", message);
                return null;
            }
            Map map = deviceByFilterVos.get(0);
            String type = map.get("Type").toString();
            if (StringUtils.isEmpty(type)) {
                log.error("conversionType111>>>>>>type is empty,message:[{}]", message);
                return null;
            }
            String deviceType;
            switch (type) {
                case LocalConstant.STRING_LOCAL_SDI_PEER_MANAGER:
                    deviceType = LocalConstant.DeviceType.LOCAL_SDI;
                    break;
                case LocalConstant.STRING_GLINK_PEER_MANAGER:
                    deviceType = LocalConstant.DeviceType.G_LINK;
                    break;
                case LocalConstant.STRING_EXTERNAL_PEER_MANAGER:
                    deviceType = LocalConstant.DeviceType.Ext;
                    break;
                default:
                    //类型不正确
                    return null;
            }
            List<Map> deviceMap = (List<Map>) map.get("Data");
            if (!CollectionUtils.isEmpty(deviceMap)) {
                if (StringUtils.equalsIgnoreCase(deviceType, LocalConstant.DeviceType.G_LINK)) {
                    return deviceMap.stream().parallel().map(
                            s -> {
                                ExtendExternal extendExternal = new ExtendExternal();
                                extendExternal.setType(deviceType);
                                extendExternal.setPeerId(s.get("IdHex").toString().toLowerCase());
                                extendExternal.setName(s.get("Name").toString());
                                extendExternal.setUrl(s.get("InputAddress").toString());
                                extendExternal.setRid(rid);
                                return extendExternal;
                            }).collect(Collectors.toList());
                } else {
                    return deviceMap.stream().parallel().map(
                            s -> {
                                String status = s.get("Status") == null ? "0" : s.get("Status").toString();
                                if (StringUtils.equalsIgnoreCase("2", status)) {
                                    status = s.get("IsLive") != null && Boolean.parseBoolean(s.get("IsLive").toString()) ? status : "1";
                                }else {
                                    status = "0";
                                }
                                Device device = new Device();
                                device.setType((String) s.get("SourceType"));
                                if (StringUtils.isEmpty((String) s.get("SourceType"))){
                                    device.setType(deviceType);
                                }
                                device.setPeerId(s.get("IdHex").toString().toLowerCase());
                                device.setName(s.get("Name").toString());
                                device.setStatus(status);
                                device.setUrl(s.get("InputAddress").toString());
                                return device;
                            }).collect(Collectors.toList());
                }
            }
        } catch (Exception e) {
            log.error("conversionType111>>>>>conversionType exception,message:[{}],e:[{}]", message, e);
        }
        return new ArrayList();
    }


    @Override
    public Result updatePlatform(DevicePlatformParam device, LoginUser loginUser) {

        if(!StringUtils.equals(loginUser.getRole(),LocalConstant.UserRole.SUPPORT)){
            throw new ServerException(ResultConstant.User.NOT_PERMISSION);
        }
        String platform = device.getPlatform();
        String peerId = device.getPeerId();
        if (StringUtils.isNotEmpty(platform) &&StringUtils.isNotEmpty(peerId)){
            Device devices = myDeviceMapper.getDeviceByPeerId(peerId);
            log.error("update the device platfrom Before : [{}]",devices);
            myDeviceMapper.updatePlatformByPeerId(peerId,platform);

            //之后需要修改memcache里面的platform;
            Device currentDevice = getCurrentDevice(peerId);
            currentDevice.setPlatform(platform);

            tpdsMemcacheClient.set(DeviceConstant.MemcacheKey.STATUS_FOR_GRIDWITCH+ device.getPeerId().toLowerCase(),  0,currentDevice);
        }
        return ResultUtil.success();

    }

    @Override
    public List<Object> getPST() {
        //从内存里获取信息
        Map<String, PST> pst = PtsPrs.getPts();
        if (CollectionUtils.isEmpty(pst)) {
            return null;
        }
        Map<String, Object> map = new HashMap<>(pst.size());
        pst.forEach((key, value) -> map.put(key, value));
        List<Object> list = new ArrayList<>();
        for (Map.Entry<String, Object> stringObjectEntry : map.entrySet()) {
            String key = stringObjectEntry.getKey();
            list.add(key);
        }
        return  list;
    }

    @Override
    public List<Object> getPSR() {

        Map<String, PSR> psr = PtsPrs.getPrs();
        if (CollectionUtils.isEmpty(psr)) {
            return null;
        }
        Map<String, Object> map = new HashMap<>(psr.size());
        psr.forEach((key, value) -> map.put(key, value));
        List<Object> list = new ArrayList<>();
        for (Map.Entry<String, Object> stringObjectEntry : map.entrySet()) {
            String key = stringObjectEntry.getKey();
            list.add(key);
        }
        return list;

    }

    @Override
    public Result addExtToReceiver(AddExtToReceiverParam param) {
        String rid = param.getRid();
        String sourceId = param.getSourceId();
        log.error("AddExtToReceiverParam message ,rid : [{}], sourceId : [{}]",rid,sourceId);
        return extService.addExtToReceiver(rid, sourceId);
    }
}
